﻿namespace HqlExample.Domain.Base
{
	public abstract class EntityBase<T> 
	{
		public virtual T ID { get; set; }

		
		#region --- Equals() and HashCode() --- 

		private int? hashCode;

		public virtual bool Equals(EntityBase<T> other)
		{
			if (null == other || !GetType().IsInstanceOfType(other))
			{
				return false;
			}
			if (ReferenceEquals(this, other))
			{
				return true;
			}

			bool otherIsTransient = Equals(other.ID, default(T));
			bool thisIsTransient = IsTransient();
			if (otherIsTransient && thisIsTransient)
			{
				return ReferenceEquals(other, this);
			}

			return other.ID.Equals(ID);
		}

		public override bool Equals(object obj)
		{
			var that = obj as EntityBase<T>;
			return Equals(that);
		}

		protected bool IsTransient()
		{
			return Equals(ID, default(T));
		}

		public override int GetHashCode()
		{
			if (!hashCode.HasValue)
			{
				hashCode = IsTransient() ? base.GetHashCode() : ID.GetHashCode();
			}
			return hashCode.Value;
		}

		#endregion
	}
}